package com.waverider.promotion.biz.manager.impl;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.iacrqq.util.DateUtil;
import com.iacrqq.util.StringUtil;
import com.taobao.api.ApiException;
import com.taobao.api.TaobaoClient;
import com.taobao.api.domain.Item;
import com.taobao.api.request.ItemGetRequest;
import com.taobao.api.request.ItemUpdateRequest;
import com.taobao.api.request.ItemsOnsaleGetRequest;
import com.taobao.api.response.ItemGetResponse;
import com.taobao.api.response.ItemUpdateResponse;
import com.taobao.api.response.ItemsOnsaleGetResponse;
import com.waverider.promotion.biz.dao.PromotionDAO;
import com.waverider.promotion.biz.dao.PromotionGoodsAssDAO;
import com.waverider.promotion.biz.manager.ItemManager;
import com.waverider.promotion.biz.manager.TemplateManager;
import com.waverider.promotion.domain.OrderDO;
import com.waverider.promotion.domain.PromotionDO;
import com.waverider.promotion.domain.PromotionGoodsAssDO;
import com.waverider.promotion.enums.PromotionStatusEnum;
import com.waverider.promotion.enums.PromotionTypeEnum;
import com.waverider.promotion.model.BaseQueryModel;
import com.waverider.promotion.model.ItemQueryModel;
import com.waverider.promotion.model.PromotionQueryModel;
import com.waverider.promotion.model.ResultModel;

/**
 * 
 * @author sihai
 * 
 */
public class ItemManagerImpl implements ItemManager {

	private static final Log logger = LogFactory.getLog(ItemManagerImpl.class);

	private PromotionDAO promotionDAO;
	private PromotionGoodsAssDAO promotionGoodsAssDAO;
	private TaobaoClient taobaoClient;

	public final void setPromotionGoodsAssDAO(
			PromotionGoodsAssDAO promotionGoodsAssDAO) {
		this.promotionGoodsAssDAO = promotionGoodsAssDAO;
	}

	private TemplateManager templateManager;

	@Override
	public void addPromotion(String sessionKey, Item item, PromotionDO promotion) {
		_update_item_promotion_info_(sessionKey, promotion, true);

		Long promotionId = promotionDAO.insert(promotion);
		// 插入promotion与goods映射关系
		PromotionGoodsAssDO promotionGoodsAssDO = new PromotionGoodsAssDO();
		promotionGoodsAssDO.setShopId(promotion.getShopId());
		promotionGoodsAssDO.setPromotionId(promotionId);
		promotionGoodsAssDO
				.setGoodsIdStr(String.valueOf(promotion.getGoodsId()));
		promotionGoodsAssDAO.insert(promotionGoodsAssDO);

	}

	@Override
	public boolean updatePromotion(String sessionKey, PromotionDO promotion,
			boolean isNew) {

		_update_item_promotion_info_(sessionKey, promotion, isNew);

		return promotionDAO.update(promotion);
	}

	@Override
	public PromotionDO getPromotionByGoodsId(Long goodsId) {
		return promotionDAO.queryByGoodsId(goodsId);
	}

	@Override
	public PromotionDO getPromotionById(Long id) {
		return promotionDAO.queryById(id);
	}

	@Override
	public ResultModel<PromotionDO> getPromotionList(
			PromotionQueryModel queryModel) {
		return ResultModel.buildResultModel(queryModel,
				promotionDAO.query(queryModel), promotionDAO.count(queryModel));
	}

	@Override
	public boolean delete(String sessionKey, Long id, Long goodsId) {
		PromotionDO promotion = this.getPromotionByGoodsId(goodsId);
		promotion.setStatus(PromotionStatusEnum.PROMOTION_STATUS_END.value());
		_update_item_promotion_info_(sessionKey, promotion, false);

		return promotionDAO.delete(id);
	}

	@Override
	public boolean syncPromotion(String sessionKey, PromotionDO promotion,
			OrderDO order) {
		Long quantity = order.getQuantity();
		Long currentOrderCount = promotion.getCurrentOrderCount();
		promotion.setCurrentOrderCount(currentOrderCount + quantity);

		PromotionTypeEnum type = PromotionTypeEnum.toEnum(promotion.getType());

		if (type == PromotionTypeEnum.PROMOTION_TYPE_DISCOUNT) {
			int currentDiscount = promotion.getCurrentDiscount();
			promotion.setCurrentDiscount(currentDiscount
					- Double.valueOf(
							(promotion.getDiscountIncreaseUnit() * quantity))
							.intValue());
		} else if (type == PromotionTypeEnum.PROMOTION_TYPE_REDUE_PRICE) {
			BigDecimal currentPrice = promotion.getCurrentPrice();
			promotion.setCurrentPrice(currentPrice.subtract(promotion
					.getPriceReduceUnit().multiply(new BigDecimal(quantity))));
		}

		return updatePromotion(sessionKey, promotion, false);
	}

	public ResultModel<Item> getItemList(String sessionKey,
			ItemQueryModel queryModel) {
		ItemsOnsaleGetRequest request = new ItemsOnsaleGetRequest();
		request.setFields("detail_url,approve_status,num_iid,title,nick,type,cid,pic_url,num,props,valid_thru,list_time,price,has_discount,has_invoice,has_warranty,has_showcase,modified,delist_time,postage_id,seller_cids,outer_id");
		request.setIsTaobao(true);
		request.setQ(queryModel.getGoodsTitle());
		request.setPageNo(queryModel.getCurrentPage());
		request.setPageSize(queryModel.getPageSize());
		request.setOrderBy("list_time:desc");
		try {
			ItemsOnsaleGetResponse response = taobaoClient.execute(request,
					sessionKey);
			if(response.getMsg() != null)
				throw new RuntimeException(response.getMsg());
			return ResultModel.buildResultModel(queryModel,
					response.getItems(), response.getTotalResults());
		} catch (ApiException e) {
			logger.error(e);
			throw new RuntimeException(e);
		}
	}

	@Override
	public Item getItem(String sessionKey, Long itemId) {
		try {
			ItemGetRequest request = new ItemGetRequest();
			request.setFields("detail_url,num_iid,title,nick,type,created,promoted_service,"
					+ "is_lightning_consignment,is_fenxiao,cid,pic_url,num,valid_thru,price,"
					+ "has_discount,freight_payer,has_invoice,has_warranty,auction_point,"
					+ "is_virtual,sell_promise,desc");
			request.setNumIid(itemId);
			ItemGetResponse response = taobaoClient
					.execute(request, sessionKey);
			return response.getItem();
		} catch (ApiException e) {
			logger.error(e);
			throw new RuntimeException(e);
		}
	}

	@Override
	public boolean updateItemPromotionInfo(String sessionKey,
			PromotionDO promotion, boolean isNew) {
		_update_item_promotion_info_(sessionKey, promotion, isNew);

		return true;
	}

	private void _update_item_promotion_info_(String sessionKey,
			PromotionDO promotion, boolean isNew) throws RuntimeException {
		try {
			PromotionStatusEnum status = PromotionStatusEnum.toEnum(promotion
					.getStatus().intValue());
			ItemUpdateRequest request = new ItemUpdateRequest();
			Item item = getItem(sessionKey, promotion.getGoodsId());
			Long itemId = item.getNumIid();
			String html = null;

			if (status == PromotionStatusEnum.PROMOTION_STATUS_NOT_START) {
				return;
			} else if (status == PromotionStatusEnum.PROMOTION_STATUS_STARTED) {
				if (isNew) {
					//
					Long initOrderCount = promotion.getInitOrderCount();
					PromotionTypeEnum type = PromotionTypeEnum.toEnum(promotion
							.getType().intValue());
					if (initOrderCount > 0) {

						BigDecimal currentPrice = null;

						if (type == PromotionTypeEnum.PROMOTION_TYPE_DISCOUNT) {
							promotion.setCurrentDiscount(100 - Double.valueOf(
									promotion.getDiscountIncreaseUnit()
											* initOrderCount).intValue());
							currentPrice = promotion.getOriginalPrice()
									.multiply(
											new BigDecimal(promotion
													.getCurrentDiscount()));
						} else if (type == PromotionTypeEnum.PROMOTION_TYPE_REDUE_PRICE) {
							currentPrice = promotion
									.getOriginalPrice()
									.subtract(
											promotion
													.getPriceReduceUnit()
													.multiply(
															new BigDecimal(
																	promotion
																			.getInitOrderCount()
																			.toString())));
						}

						promotion.setCurrentPrice(currentPrice);
						 request.setPrice(currentPrice.toString());
					}
				} else {
					 request.setPrice(promotion.getCurrentPrice().toString());
				}

				html = _build_promotion_info_(sessionKey, promotion);
			} else if (status == PromotionStatusEnum.PROMOTION_STATUS_END) {
				// request.setPrice(promotion.getOriginalPrice().toString());
				html = "";
			} else {
				throw new RuntimeException(new StringBuilder(
						"[ERROR] Unkown status of promotion:").append(
						promotion.getStatus().intValue()).toString());
			}

			request.setNumIid(itemId);
			String desc = item.getDesc();
			if (StringUtil.isBlank(desc)) {
				throw new RuntimeException(
						"[ERROR] Taoabo API return item.desc is blank");
			}
			filterExistsTemplate(item);
			request.setDesc(html + item.getDesc());
			ItemUpdateResponse response = taobaoClient.execute(request,
					sessionKey);
		} catch (ApiException e) {
			logger.error(e);
			throw new RuntimeException(e);
		} catch (Exception e) {
			logger.error(e);
			throw new RuntimeException(e);
		}
	}

	private String _build_promotion_info_(String sessionKey,
			PromotionDO promotion) throws Exception {
		if (promotion == null)
			return "";
		PromotionStatusEnum status = PromotionStatusEnum.toEnum(promotion
				.getStatus().intValue());

		if (status != PromotionStatusEnum.PROMOTION_STATUS_STARTED) {
			return "";
		}

		PromotionQueryModel queryModel = PromotionQueryModel.buildQueryModel(
				promotion.getShopId(),
				PromotionStatusEnum.PROMOTION_STATUS_STARTED.value(), null,
				null, 1L, BaseQueryModel.DEFAULT_PAGE_SIZE);
		Map<String, Object> context = new HashMap<String, Object>();
		context.put("dateUtil", new DateUtil());
		context.put("promotion", promotion);
		context.put("others", this.getPromotionList(queryModel).getItemList());
		return templateManager.getHTML("750detail", context);
	}

	public void setPromotionDAO(PromotionDAO promotionDAO) {
		this.promotionDAO = promotionDAO;
	}

	public void setTaobaoClient(TaobaoClient taobaoClient) {
		this.taobaoClient = taobaoClient;
	}

	public void setTemplateManager(TemplateManager templateManager) {
		this.templateManager = templateManager;
	}

	@Override
	public boolean recommendOne(String sessionKey, Long itemId, Long promotionId) {
		PromotionDO promotion = promotionDAO.queryById(promotionId);
		return recommendOne(sessionKey, itemId, promotion);
	}

	private boolean recommendOne(String sessionKey, Long itemId,
			PromotionDO promotion) {
		try {
			Item item = getItem(sessionKey, itemId);
			ItemUpdateRequest request = new ItemUpdateRequest();
			request.setNumIid(itemId);
			filterExistsTemplate(item);
			if (StringUtils.isNotBlank(item.getDesc())) {
				String html = _build_promotion_info_(sessionKey, promotion);
				request.setDesc(new StringBuilder().append(html)
						.append(item.getDesc()).toString());
			}
			taobaoClient.execute(request, sessionKey);
			return true;
		} catch (ApiException e) {
			logger.error(e.getMessage(), e);
			throw new RuntimeException(e);
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
		}
		return false;
	}

	@Override
	public boolean recommendSome(String sessionKey, List<Long> itemIdList,
			Long promotionId, Long shopId) {
		PromotionDO promotion = promotionDAO.queryById(promotionId);
		for (Long itemId : itemIdList)
			this.recommendOne(sessionKey, itemId, promotion);
		// 更新promotion与goods映射关系
		updatePromotionGoodsAss(promotion, itemIdList, shopId, 0);
		return true;
	}

	@Override
	public boolean recommendAll(String sessionKey, Long promotionId, Long shopId) {
		ItemQueryModel queryModel = new ItemQueryModel();
		queryModel.setPageSize(200L);
		queryModel.setCurrentPage(1L);
		int currPage = 1;
		List<Long> itemIdList = new ArrayList<Long>();
		PromotionDO promotion = promotionDAO.queryById(promotionId);
		while (true) {
			ResultModel<Item> result = this.getItemList(sessionKey, queryModel);
			if (result == null || result.getItemList() == null
					|| result.getItemList().size() == 0)
				break;

			for (Item item : result.getItemList()) {
				this.recommendOne(sessionKey, item.getNumIid(), promotion);
				itemIdList.add(item.getNumIid());
			}
			++currPage;
			queryModel.setCurrentPage(Long.valueOf(currPage));
		}
		// 更新promotion与goods映射关系
		updatePromotionGoodsAss(promotion, itemIdList, shopId, 1);
		return true;
	}

	private void filterExistsTemplate(Item item) {
		String desc = item.getDesc();
		if (StringUtils.isNotBlank(desc)
				&& desc.contains("woyaozhekou_falg@!@")) {
			desc = desc
					.replaceFirst(
							"<div style=\"color: #333333;font-family: 微软雅黑.*?woyaozhekou_falg@!@</div>",
							"");
			item.setDesc(desc);
		}
	}

	public static void main(String[] args) {
		// String MARK =
		// "<div style=\"font-family: 微软雅黑 宋体 verdana tahoma sans-serif;color: #333333;width: 716.0px;margin-left: 30.0px;border: 2.0px solid #95bd5a;font-size: 16.0px;margin-bottom: 10.0px;\">.*</div>";
		String text = "<div style=\"font-family: 微软雅黑 宋体 verdana tahoma sans-serif;color: #333333;width: 716.0px;margin-left: 30.0px;border: 2.0px solid #95bd5a;font-size: 16.0px;margin-bottom: 10.0px;\"><div style=\"height: 135.0px;width: 100.0%;border-bottom: 1.0px solid #41d535;overflow: hidden;\"><img src=\"http://www.sihai.com:9090/images/banner.png\"></div><div style=\"float: left;height: 332.0px;width: 519.0px;\"><table background=\"http://www.sihai.com:9090/images/back.png\" style=\"margin-left: -26.0px;width: 560.0px;margin-top: 20.0px;\"><tr><td><div style=\"padding-left: 40.0px;margin-bottom: 6.0px;\"><a href=\"http://item.taobao.com/item.htm?id=13369343893\" style=\"color: #333333;font-weight: bold;\">大大的优惠</a></div><div style=\"width: 286.0px;float: left;\"><div style=\"color: #ffffff;font-size: 32.0px;font-weight: bold;margin: 13.0px 5.0px;text-align: right;width: 270.0px;\"><span style=\"font-size: 16.0px;\">当前折扣：</span>97<a href=\"http://item.taobao.com/item.htm?id=13369343893\" style=\"display: block;float: right;margin-top: 10.0px;margin-right: 7.0px;height: 36.0px;width: 78.0px;margin-left: 20.0px;\"></a></div><a href=\"http://item.taobao.com/item.htm?id=13369343893\" style=\"height: 36.0px;width: 78.0px;\"></a><div style=\"margin-left: 30.0px;overflow: auto;\"><p style=\"float: left;text-align: center;width: 84.0px;margin: 0;\">原价<br> ￥</p><p style=\"float: left;text-align: center;width: 84.0px;margin: 0;\">最高折扣<br> 70%</p><p style=\"float: left;text-align: center;width: 84.0px;margin: 0;\">已卖出<br> 10</p></div><div style=\"color: red;margin-left: 32.0px;padding: 10.0px 0.0pt;text-align: center;width: 244.0px;text-decoration: blink;\">还剩10名可以享受最高折扣！</div><div style=\"color: #ffffff;background-color: #333333;margin-left: 32.0px;padding: 10.0px 0;text-align: center;width: 244.0px;\">每增加1人购买，多打折0.3%！</div><div style=\"margin-left: 32.0px;width: 244.0px;padding: 10.0px 0;\">截止时间: 11-18 00:31<br> 还有:<span style=\"color: #14910b;font-weight: bold;font-size: 20.0px;\">10天23小时59分钟</span></div></div><a href=\"http://item.taobao.com/item.htm?id=13369343893\" style=\"display: block;float: right;margin: 10.0px 23.0px 0 0;\"><img height=\"250\" src=\"http://img02.taobaocdn.com/bao/uploaded/i2/T1RyqyXjpmXXbWGxZU_015119.jpg\" width=\"250\"></a></td></tr></table></div><div style=\"float: right;height: 322.0px;width: 180.0px;margin: 10.0px 10.0px 0 0;\"><img src=\"http://www.sihai.com:9090/images/instruction.png\"></div><div style=\"clear: both;\">&nbsp;</div></div><div style=\"display:none\">woyaozhekou_falg@!@</div>";
		System.out.println(text.replaceAll(
				"<div style=\"font-family:.*?woyaozhekou_falg@!@</div>", ""));
	}

	@Override
	public List<PromotionDO> getExpirePromitonByShopId(Long shopId) {
		if (shopId == null)
			return null;
		return promotionDAO.queryExpirePromotionByShopId(shopId);
	}

	private void updatePromotionGoodsAss(PromotionDO promotion,
			List<Long> itemIdList, Long shopId, int flag) {

		if (itemIdList == null || itemIdList.isEmpty() || shopId == null)
			return;
		// 推广到所有商品
		if (flag == 1) {
			promotionGoodsAssDAO.deleteByShopId(shopId);
			if (promotion != null) {
				PromotionGoodsAssDO promotionGoodsAssDO = new PromotionGoodsAssDO();
				promotionGoodsAssDO.setPromotionId(promotion.getId());
				promotionGoodsAssDO.setShopId(shopId);
				StringBuilder sb = new StringBuilder();
				for (Long itemId : itemIdList)
					sb.append(itemId).append(",");
				promotionGoodsAssDO.setGoodsIdStr(sb.substring(0, sb.toString()
						.length() - 1));
				promotionGoodsAssDAO.insert(promotionGoodsAssDO);
			}

		}
		// 推广到部分商品
		if (flag == 0) {
			List<PromotionGoodsAssDO> promotionGoodsAssDOList = promotionGoodsAssDAO
					.queryByShopId(shopId);
			// 删除推广
			if (promotion == null) {
				for (PromotionGoodsAssDO promotionGoodsAssDO : promotionGoodsAssDOList) {
					String retStr = buildStr(
							promotionGoodsAssDO.getGoodsIdStr(), itemIdList);
					if ("".equals(retStr))
						promotionGoodsAssDAO.deleteById(promotionGoodsAssDO
								.getId());
					else {
						promotionGoodsAssDO.setGoodsIdStr(retStr);
						promotionGoodsAssDAO.update(promotionGoodsAssDO);
					}
				}
			} else {
				// 修改推广
				boolean idExists = false;
				StringBuilder sb = new StringBuilder();
				for (Long itemId : itemIdList)
					sb.append(itemId).append(",");
				String temp = sb.substring(0, sb.toString().length() - 1);

				for (PromotionGoodsAssDO promotionGoodsAssDO : promotionGoodsAssDOList) {
					String retStr = buildStr(
							promotionGoodsAssDO.getGoodsIdStr(), itemIdList);
					if (promotionGoodsAssDO.getPromotionId().equals(
							promotion.getId())) {
						idExists = true;
						retStr = retStr +"," + temp;
					}
					if ("".equals(retStr))
						promotionGoodsAssDAO.deleteById(promotionGoodsAssDO
								.getId());
					else {
						promotionGoodsAssDO.setGoodsIdStr(retStr);
						promotionGoodsAssDAO.update(promotionGoodsAssDO);
					}
				}
				if (!idExists) {
					PromotionGoodsAssDO promotionGoodsAssDO = new PromotionGoodsAssDO();
					promotionGoodsAssDO.setPromotionId(promotion.getId());
					promotionGoodsAssDO.setShopId(shopId);
					promotionGoodsAssDO.setGoodsIdStr(temp);
					promotionGoodsAssDAO.insert(promotionGoodsAssDO);
				}
			}
		}
	}

	private String buildStr(String goodsIdStr, List<Long> itemIdList) {
		String temp =goodsIdStr;
		for (Long itemId : itemIdList) {
			if (temp.contains(String.valueOf(itemId)))
				temp = temp.replaceFirst(String.valueOf(itemId), "");
		}
		String[] strs = temp.split(",");
		StringBuilder sb = new StringBuilder();
		for (String str : strs)
			if (!"".equals(str))
				sb.append(str).append(",");
		if (sb.length() > 0)
			return sb.substring(0, sb.length() - 1);
		return "";
	}

	@Override
	public int getValidatePromotionCountByShopId(Long shopId) {
		return promotionDAO.getValidatePromotionCountByShopId(shopId);
	}
}
